package de.alt.rest.util;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang3.StringUtils;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

import de.alt.rest.constants.Constants;
import de.alt.rest.exception.MailException;
import de.alt.rest.exception.NotLoggedInException;

/**
 * The Class GeneralSuperUtil.
 */
public class GeneralSuperUtil {

	/** The Constant log. */
	private static final Logger log = Logger.getLogger(GeneralSuperUtil.class.getName());

	/**
	 * Calculates a MD5 checksum for the given String.
	 *
	 * @param s the s
	 * @return the string
	 */
	public String md5(String s) {
		try {
			byte[] bytesOfMessage = s.getBytes("UTF-8");
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] thedigest = md.digest(bytesOfMessage);
			BigInteger bigInt = new BigInteger(1, thedigest);
			return bigInt.toString(16);
		} catch (Exception e) {
			log.warning(e.getMessage());
		}
		return null;
	}

	/**
	 * Gets entity by id.
	 *
	 * @param name the name of the entity
	 * @param id the id
	 * @return the by id
	 */
	public Entity getById(String name, String id) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();
		Key key = KeyFactory.createKey(name, id);
		Query query = new Query(name, key);
		return datastore.prepare(query).asSingleEntity();
	}

	/**
	 * RegEx wrapper method.
	 *
	 * @param text the text
	 * @param regex the regex
	 * @return true, if successful
	 */
	public boolean checkRegEx(String text, String regex) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(text);
		return matcher.matches();
	}
	
	/**
	 * Send mail.
	 *
	 * @param mailTo the mail to
	 * @param subject the subject
	 * @param text the text
	 * @throws MailException the mail exception
	 * @throws UnsupportedEncodingException the unsupported encoding exception
	 * @throws MessagingException the messaging exception
	 */
	public void sendMail(String mailTo, String subject, String text) throws MailException, UnsupportedEncodingException, MessagingException {
		if (StringUtils.isEmpty(mailTo) || StringUtils.isEmpty(subject) || StringUtils.isEmpty(text)) {
			throw new MailException();
		}

		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);

		Message msg = new MimeMessage(session);
		msg.setFrom(new InternetAddress(Constants.ADMAIN_MAIL, Constants.ADMAIN_NAME));
		msg.addRecipient(Message.RecipientType.TO, new InternetAddress(mailTo));
		msg.setSubject(subject);
		msg.setText(text);

		Transport.send(msg);
	}
	
	/**
	 * Checks if is user logged in.
	 *
	 * @return the user
	 * @throws NotLoggedInException the not logged in exception
	 */
	public User isUserLoggedIn() throws NotLoggedInException {
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		if (user == null)
			throw new NotLoggedInException();
		return user;
	}
	
	/**
	 * Gets the log in link.
	 *
	 * @param serverName the server name
	 * @return the log in link
	 */
	public Map<String, Object> getLogInLink(String serverName) {
		
		Map<String, Object> result = new HashMap<String, Object>();
		UserService userService = UserServiceFactory.getUserService();
		
		try {
			User user = isUserLoggedIn();
			if (!Constants.ADMAIN_MAIL.equals(user.getEmail())) {
				log.info(user.toString());
			}
			result.put("link", "<a href='" + userService.createLogoutURL("#") + "'> LogOut </a>");
			result.put("loggedIn", true);
		} catch (NotLoggedInException e) {
			result.put("link", "<a href='" + userService.createLoginURL(serverName) + "'> LogIn </a>");
			result.put("loggedIn", false);
		}
		
		
		return result;
	}
}
